package com.fsserver.core.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.fsserver.config.AlipayConfig;
import com.fsserver.core.dto.PaymentRequestDTO;
import com.fsserver.core.service.AlipayService;
import com.fsserver.core.vo.PaymentResponseVO;
import com.fsserver.core.vo.RequestNotification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付服务实现类
 */
@Slf4j
@Service
public class AlipayServiceImpl implements AlipayService {

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private AlipayConfig alipayConfig;

    @Override
    public PaymentResponseVO createPayment(PaymentRequestDTO requestDTO) {
        // 根据支付类型选择不同的支付方式
        String payType = requestDTO.getPaymentType();
        
        // 记录日志
        log.info("创建支付宝支付订单, 类型: {}, 订单号: {}", payType, requestDTO.getOrderNo());
        
        try {
            // 根据支付类型调用不同的支付方法
            if ("JSAPI".equals(payType) || "MINI".equals(payType)) {
                // 小程序、生活号支付
                return createJsapiPayment(requestDTO);
            } else if ("MICRO".equals(payType)) {
                // 付款码支付
                return createMicroPayment(requestDTO);
            } else if ("H5".equals(payType)) {
                // H5支付
                return createH5Payment(requestDTO);
            } else if ("WEB".equals(payType)) {
                // PC网页支付
                return createWebPayment(requestDTO);
            } else if ("APP".equals(payType)) {
                // APP支付
                return createAppPayment(requestDTO);
            } else {
                // 不支持的支付类型
                log.error("不支持的支付宝支付类型: {}", payType);
                throw new IllegalArgumentException("不支持的支付宝支付类型: " + payType);
            }
        } catch (Exception e) {
            log.error("创建支付宝支付订单失败, 订单号: {}, 原因: {}", requestDTO.getOrderNo(), e.getMessage(), e);
            PaymentResponseVO errorResponse = new PaymentResponseVO();
            errorResponse.setOrderNo(requestDTO.getOrderNo());
            errorResponse.setPaymentType("ALIPAY");
            errorResponse.setStatus("FAIL");
            errorResponse.setErrorMsg("创建支付宝支付订单失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 创建JSAPI支付（小程序、生活号）
     * 
     * @param requestDTO 支付请求DTO
     * @return 支付响应VO
     * @throws AlipayApiException 支付宝API异常
     */
    private PaymentResponseVO createJsapiPayment(PaymentRequestDTO requestDTO) throws AlipayApiException {
        // 验证必要参数
        if (StringUtils.isEmpty(requestDTO.getOpenId())) {
            throw new IllegalArgumentException("JSAPI支付必须提供用户ID");
        }
        
        // 构建请求对象
        AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
        
        // 配置通知地址
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        
        // 构建业务参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", requestDTO.getOrderNo());
        bizContent.put("total_amount", convertCentToYuan(requestDTO.getAmount()));
        bizContent.put("subject", requestDTO.getDescription());
        bizContent.put("buyer_id", requestDTO.getOpenId());
        
        request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
        
        // 调用支付宝API
        log.info("调用支付宝JSAPI支付接口, 订单号: {}", requestDTO.getOrderNo());
        AlipayTradeCreateResponse response = alipayClient.execute(request);
        
        // 判断是否成功
        if (!response.isSuccess()) {
            log.error("调用支付宝JSAPI支付接口失败, 订单号: {}, 错误码: {}, 错误信息: {}", 
                    requestDTO.getOrderNo(), response.getCode(), response.getMsg());
            throw new AlipayApiException("调用支付宝JSAPI支付接口失败: " + response.getMsg());
        }
        
        // 构建响应对象
        PaymentResponseVO responseVO = new PaymentResponseVO();
        responseVO.setOrderNo(requestDTO.getOrderNo());
        responseVO.setPaymentType("ALIPAY");
        responseVO.setStatus("SUCCESS");
        responseVO.setTransactionId(response.getTradeNo());
        
        // 构建JSAPI支付参数
        Map<String, String> jsapiParams = new HashMap<>();
        jsapiParams.put("tradeNo", response.getTradeNo());
        
        responseVO.setJsapiParams(jsapiParams);
        
        log.info("支付宝JSAPI支付订单创建成功, 订单号: {}, 支付宝交易号: {}", 
                requestDTO.getOrderNo(), response.getTradeNo());
        return responseVO;
    }

    /**
     * 创建付款码支付
     * 
     * @param requestDTO 支付请求DTO
     * @return 支付响应VO
     * @throws AlipayApiException 支付宝API异常
     */
    private PaymentResponseVO createMicroPayment(PaymentRequestDTO requestDTO) throws AlipayApiException {
        // 验证必要参数
        if (StringUtils.isEmpty(requestDTO.getAuthCode())) {
            throw new IllegalArgumentException("付款码支付必须提供授权码");
        }
        
        // 构建请求对象
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        
        // 配置通知地址
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        
        // 构建业务参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", requestDTO.getOrderNo());
        bizContent.put("total_amount", convertCentToYuan(requestDTO.getAmount()));
        bizContent.put("subject", requestDTO.getDescription());
        bizContent.put("auth_code", requestDTO.getAuthCode());
        bizContent.put("scene", "bar_code");
        
        request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
        
        // 调用支付宝API
        log.info("调用支付宝付款码支付接口, 订单号: {}, 授权码: {}", requestDTO.getOrderNo(), requestDTO.getAuthCode());
        AlipayTradePayResponse response = alipayClient.execute(request);
        
        // 构建响应对象
        PaymentResponseVO responseVO = new PaymentResponseVO();
        responseVO.setOrderNo(requestDTO.getOrderNo());
        responseVO.setPaymentType("ALIPAY_MICRO");
        
        // 判断是否成功
        if (response.isSuccess()) {
            responseVO.setStatus("SUCCESS");
            responseVO.setTransactionId(response.getTradeNo());
            log.info("支付宝付款码支付成功, 订单号: {}, 支付宝交易号: {}", 
                    requestDTO.getOrderNo(), response.getTradeNo());
        } else {
            // 处理特殊状态码:10000表示成功,20000表示处理中,40004表示处理失败
            if ("10000".equals(response.getCode())) {
                responseVO.setStatus("SUCCESS");
            } else if ("20000".equals(response.getCode())) {
                responseVO.setStatus("PROCESSING");
            } else {
                responseVO.setStatus("FAIL");
                responseVO.setErrorMsg(response.getMsg());
                log.error("支付宝付款码支付失败, 订单号: {}, 错误码: {}, 错误信息: {}", 
                        requestDTO.getOrderNo(), response.getCode(), response.getMsg());
            }
        }
        
        return responseVO;
    }

    /**
     * 创建H5支付
     * 
     * @param requestDTO 支付请求DTO
     * @return 支付响应VO
     * @throws AlipayApiException 支付宝API异常
     */
    private PaymentResponseVO createH5Payment(PaymentRequestDTO requestDTO) throws AlipayApiException {
        // 构建请求对象
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        
        // 配置通知地址
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        request.setReturnUrl(alipayConfig.getReturnUrl());
        
        // 构建业务参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", requestDTO.getOrderNo());
        bizContent.put("total_amount", convertCentToYuan(requestDTO.getAmount()));
        bizContent.put("subject", requestDTO.getDescription());
        bizContent.put("product_code", "QUICK_WAP_WAY");
        
        request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
        
        // 调用支付宝API
        log.info("调用支付宝H5支付接口, 订单号: {}", requestDTO.getOrderNo());
        AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
        
        // 构建响应对象
        PaymentResponseVO responseVO = new PaymentResponseVO();
        responseVO.setOrderNo(requestDTO.getOrderNo());
        responseVO.setPaymentType("ALIPAY_H5");
        responseVO.setStatus("SUCCESS");
        responseVO.setHtmlForm(response.getBody());
        
        log.info("支付宝H5支付订单创建成功, 订单号: {}", requestDTO.getOrderNo());
        return responseVO;
    }

    /**
     * 创建PC网页支付
     * 
     * @param requestDTO 支付请求DTO
     * @return 支付响应VO
     * @throws AlipayApiException 支付宝API异常
     */
    private PaymentResponseVO createWebPayment(PaymentRequestDTO requestDTO) throws AlipayApiException {
        // 构建请求对象
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        
        // 配置通知地址
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        request.setReturnUrl(alipayConfig.getReturnUrl());
        
        // 构建业务参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", requestDTO.getOrderNo());
        bizContent.put("total_amount", convertCentToYuan(requestDTO.getAmount()));
        bizContent.put("subject", requestDTO.getDescription());
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        
        request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
        
        // 调用支付宝API
        log.info("调用支付宝PC网页支付接口, 订单号: {}", requestDTO.getOrderNo());
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
        
        // 构建响应对象
        PaymentResponseVO responseVO = new PaymentResponseVO();
        responseVO.setOrderNo(requestDTO.getOrderNo());
        responseVO.setPaymentType("ALIPAY_WEB");
        responseVO.setStatus("SUCCESS");
        responseVO.setHtmlForm(response.getBody());
        
        log.info("支付宝PC网页支付订单创建成功, 订单号: {}", requestDTO.getOrderNo());
        return responseVO;
    }

    /**
     * 创建APP支付
     * 
     * @param requestDTO 支付请求DTO
     * @return 支付响应VO
     * @throws AlipayApiException 支付宝API异常
     */
    private PaymentResponseVO createAppPayment(PaymentRequestDTO requestDTO) throws AlipayApiException {
        // 构建请求对象
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        
        // 配置通知地址
        request.setNotifyUrl(alipayConfig.getNotifyUrl());
        
        // 构建业务参数
        Map<String, Object> bizContent = new HashMap<>();
        bizContent.put("out_trade_no", requestDTO.getOrderNo());
        bizContent.put("total_amount", convertCentToYuan(requestDTO.getAmount()));
        bizContent.put("subject", requestDTO.getDescription());
        bizContent.put("product_code", "QUICK_MSECURITY_PAY");
        
        request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
        
        // 调用支付宝API
        log.info("调用支付宝APP支付接口, 订单号: {}", requestDTO.getOrderNo());
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
        
        // 构建响应对象
        PaymentResponseVO responseVO = new PaymentResponseVO();
        responseVO.setOrderNo(requestDTO.getOrderNo());
        responseVO.setPaymentType("ALIPAY_APP");
        
        // 判断是否成功
        if (response.isSuccess()) {
            responseVO.setStatus("SUCCESS");
            
            // 获取订单信息，APP端用于拉起支付宝
            Map<String, String> appParams = new HashMap<>();
            appParams.put("orderInfo", response.getBody());
            responseVO.setAppParams(appParams);
            
            log.info("支付宝APP支付订单创建成功, 订单号: {}", requestDTO.getOrderNo());
        } else {
            responseVO.setStatus("FAIL");
            responseVO.setErrorMsg(response.getMsg());
            log.error("支付宝APP支付失败, 订单号: {}, 错误码: {}, 错误信息: {}", 
                    requestDTO.getOrderNo(), response.getCode(), response.getMsg());
        }
        
        return responseVO;
    }

    @Override
    public Map<String, Object> queryOrder(String orderNo) {
        try {
            log.info("查询支付宝订单, 订单号: {}", orderNo);
            
            // 构建请求对象
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            
            // 构建业务参数
            Map<String, Object> bizContent = new HashMap<>();
            bizContent.put("out_trade_no", orderNo);
            
            request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
            
            // 调用支付宝API
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("orderNo", orderNo);
            
            // 判断是否成功
            if (response.isSuccess()) {
                result.put("tradeStatus", response.getTradeStatus());
                result.put("transactionId", response.getTradeNo());
                result.put("totalAmount", convertYuanToCent(response.getTotalAmount()));
                result.put("buyerId", response.getBuyerUserId());
                result.put("tradeNo", response.getTradeNo());
                
                log.info("查询支付宝订单成功, 订单号: {}, 状态: {}", orderNo, response.getTradeStatus());
            } else {
                result.put("success", false);
                result.put("errorCode", response.getCode());
                result.put("errorMsg", response.getMsg());
                
                log.error("查询支付宝订单失败, 订单号: {}, 错误码: {}, 错误信息: {}", 
                        orderNo, response.getCode(), response.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            log.error("查询支付宝订单异常, 订单号: {}, 原因: {}", orderNo, e.getMessage(), e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("orderNo", orderNo);
            errorResult.put("success", false);
            errorResult.put("errorMsg", "查询订单异常: " + e.getMessage());
            return errorResult;
        }
    }

    @Override
    public boolean closeOrder(String orderNo) {
        try {
            log.info("关闭支付宝订单, 订单号: {}", orderNo);
            
            // 构建请求对象
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            
            // 构建业务参数
            Map<String, Object> bizContent = new HashMap<>();
            bizContent.put("out_trade_no", orderNo);
            
            request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
            
            // 调用支付宝API
            AlipayTradeCloseResponse response = alipayClient.execute(request);
            
            // 判断是否成功
            if (response.isSuccess()) {
                log.info("关闭支付宝订单成功, 订单号: {}", orderNo);
                return true;
            } else {
                log.error("关闭支付宝订单失败, 订单号: {}, 错误码: {}, 错误信息: {}", 
                        orderNo, response.getCode(), response.getMsg());
                return false;
            }
        } catch (Exception e) {
            log.error("关闭支付宝订单异常, 订单号: {}, 原因: {}", orderNo, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public Map<String, Object> refund(String orderNo, String refundNo, Long totalAmount, Long refundAmount, String reason) {
        try {
            log.info("申请支付宝退款, 订单号: {}, 退款单号: {}, 退款金额: {}", orderNo, refundNo, refundAmount);
            
            // 构建请求对象
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            
            // 构建业务参数
            Map<String, Object> bizContent = new HashMap<>();
            bizContent.put("out_trade_no", orderNo);
            bizContent.put("out_request_no", refundNo);
            bizContent.put("refund_amount", convertCentToYuan(refundAmount));
            
            if (!StringUtils.isEmpty(reason)) {
                bizContent.put("refund_reason", reason);
            }
            
            request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
            
            // 调用支付宝API
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("orderNo", orderNo);
            result.put("refundNo", refundNo);
            
            // 判断是否成功
            if (response.isSuccess()) {
                result.put("success", true);
                result.put("tradeNo", response.getTradeNo());
                result.put("refundAmount", convertYuanToCent(response.getRefundFee()));
                result.put("fundChange", response.getFundChange());
                result.put("refundTime", response.getGmtRefundPay());
                
                log.info("申请支付宝退款成功, 订单号: {}, 退款单号: {}, 支付宝交易号: {}", 
                        orderNo, refundNo, response.getTradeNo());
            } else {
                result.put("success", false);
                result.put("errorCode", response.getCode());
                result.put("errorMsg", response.getMsg());
                
                log.error("申请支付宝退款失败, 订单号: {}, 退款单号: {}, 错误码: {}, 错误信息: {}", 
                        orderNo, refundNo, response.getCode(), response.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            log.error("申请支付宝退款异常, 订单号: {}, 退款单号: {}, 原因: {}", 
                    orderNo, refundNo, e.getMessage(), e);
            
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("orderNo", orderNo);
            errorResult.put("refundNo", refundNo);
            errorResult.put("success", false);
            errorResult.put("errorMsg", "申请退款异常: " + e.getMessage());
            return errorResult;
        }
    }

    @Override
    public Map<String, Object> queryRefund(String refundNo) {
        try {
            log.info("查询支付宝退款, 退款单号: {}", refundNo);
            
            // 构建请求对象
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            
            // 构建业务参数
            Map<String, Object> bizContent = new HashMap<>();
            bizContent.put("out_request_no", refundNo);
            
            request.setBizContent(com.alibaba.fastjson.JSON.toJSONString(bizContent));
            
            // 调用支付宝API
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("refundNo", refundNo);
            
            // 判断是否成功
            if (response.isSuccess()) {
                result.put("success", true);
                result.put("orderNo", response.getOutTradeNo());
                result.put("tradeNo", response.getTradeNo());
                result.put("refundAmount", convertYuanToCent(response.getRefundAmount()));
                result.put("refundStatus", response.getRefundStatus());
                result.put("refundReason", response.getRefundReason());
                
                log.info("查询支付宝退款成功, 退款单号: {}, 状态: {}", refundNo, response.getRefundStatus());
            } else {
                result.put("success", false);
                result.put("errorCode", response.getCode());
                result.put("errorMsg", response.getMsg());
                
                log.error("查询支付宝退款失败, 退款单号: {}, 错误码: {}, 错误信息: {}", 
                        refundNo, response.getCode(), response.getMsg());
            }
            
            return result;
        } catch (Exception e) {
            log.error("查询支付宝退款异常, 退款单号: {}, 原因: {}", refundNo, e.getMessage(), e);
            
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("refundNo", refundNo);
            errorResult.put("success", false);
            errorResult.put("errorMsg", "查询退款异常: " + e.getMessage());
            return errorResult;
        }
    }

    @Override
    public boolean handlePaymentNotification(RequestNotification notification) {
        try {
            log.info("处理支付宝支付通知, 请求ID: {}", notification.getRequestId());
            
            // 获取通知参数
            Map<String, String> params = notification.getParameters();
            
            // 验签
            boolean signVerified = verifyNotification(params);
            if (!signVerified) {
                log.error("支付宝支付通知验签失败");
                return false;
            }
            
            // 处理通知
            String tradeStatus = params.get("trade_status");
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                // 支付成功，更新订单状态
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                String totalAmount = params.get("total_amount");
                
                log.info("支付宝支付成功, 订单号: {}, 支付宝交易号: {}, 金额: {}", 
                        outTradeNo, tradeNo, totalAmount);
                
                // TODO: 更新订单状态的业务逻辑
                
                return true;
            } else {
                log.warn("支付宝支付结果未成功, 状态: {}", tradeStatus);
                return false;
            }
        } catch (Exception e) {
            log.error("处理支付宝支付通知异常: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean handleRefundNotification(RequestNotification notification) {
        try {
            log.info("处理支付宝退款通知, 请求ID: {}", notification.getRequestId());
            
            // 获取通知参数
            Map<String, String> params = notification.getParameters();
            
            // 验签
            boolean signVerified = verifyNotification(params);
            if (!signVerified) {
                log.error("支付宝退款通知验签失败");
                return false;
            }
            
            // 处理通知
            // 注意：支付宝退款没有专门的通知，而是在交易关闭通知中处理
            String tradeStatus = params.get("trade_status");
            if ("TRADE_CLOSED".equals(tradeStatus)) {
                // 退款成功，更新退款状态
                String outTradeNo = params.get("out_trade_no");
                String tradeNo = params.get("trade_no");
                
                log.info("支付宝退款成功, 订单号: {}, 支付宝交易号: {}", outTradeNo, tradeNo);
                
                // TODO: 更新退款状态的业务逻辑
                
                return true;
            } else {
                log.warn("支付宝退款结果未成功, 状态: {}", tradeStatus);
                return false;
            }
        } catch (Exception e) {
            log.error("处理支付宝退款通知异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 验证支付宝通知签名
     *
     * @param params 通知参数
     * @return 验证结果
     */
    private boolean verifyNotification(Map<String, String> params) {
        // TODO: 实现支付宝通知验签逻辑
        // 此处应该使用AlipaySignature.rsaCheckV1()方法验证签名
        return true;
    }

    /**
     * 将分转换为元
     *
     * @param amount 金额（分）
     * @return 金额（元）
     */
    private String convertCentToYuan(Long amount) {
        if (amount == null) {
            return "0";
        }
        return new BigDecimal(amount).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString();
    }

    /**
     * 将元转换为分
     *
     * @param amount 金额（元）
     * @return 金额（分）
     */
    private Long convertYuanToCent(String amount) {
        if (StringUtils.isEmpty(amount)) {
            return 0L;
        }
        return new BigDecimal(amount).multiply(new BigDecimal(100)).longValue();
    }
} 